/**
* @file         
* @brief		特殊矩阵压缩.
* @details	    基本功能演示
* @author		conkty@126.com
* @date		    2023
* @version	    v0.1
* @par 更新记录:         
*	v0.1: 初建\n
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

const int N = 4;

enum MatrixType
{
    TopTri,     // 上三角
    BottomTri,  // 下三角
    Symm        // 对称
};

int array_index(int i, int j, enum MatrixType type) {
    int k = -1;
    switch (type)
    {
    case Symm:
        {
            k = i *(i + 1);
            k = k >> 1;  // 除以2
            k += j;
        }
        break;
    case TopTri:
        {
            k = i *((N<<1)-i + 1);
            k = k >> 1;  // 除以2
            k += j-i;
        }
        break;
    case BottomTri:
        {
            k = i *(i + 1);
            k = k >> 1;  // 除以2
            k += j;
        }
        break;
    default:
            k = -1;
        break;
    }

    return k;
}

int zip_to_array(int arr[], int m[][N], enum MatrixType type) {
    printf("zipping ... \n");

    int k = 0;
    if(Symm == type || BottomTri == type)
        for (int i = 0; i < N; ++i)
        {
            for (int j = 0; j <= i; ++j) {
                arr[k++] = m[i][j];
            }
        }
    else 
        for (int i = 0; i < N; ++i)
        {
            for (int j = i; j < N; ++j) {
                arr[k++] = m[i][j];
            }
        }

    return 0;
}

int access(int arr[], int i, int j, enum MatrixType type) {
     printf("to ... \n");
    int k = array_index(i, j, type);
    return arr[k];
}

void display(int arr[], enum MatrixType type) {
    printf("zipped matrix: \n");
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++i) {
            int c = -11;
            if(Symm == type) {
                c = i>=j?access(arr, i, j, type):access(arr, j, i, type);
            }
            
            printf("%d ", c);
        }
        printf("\n");
    }
    printf("\n");
}

int main()
{
    int matrix_symm[][N] = {
        1, 3, 5, 9,
        3, -6, 2, 4,
        5, 2, 0, -2,
        9, 4, -2, 8
    };

    int matrix_top[][N] = {
        1, 3, 5, 9,
        0, -6, 2, 4,
        0, 0, 0, -2,
        0, 0, 0, 8
    };

    int matrix_bottom[][N] = {
        1, 0, 0, 0,
        3, -6, 0, 0,
        5, 2, 0, 0,
        9, 4, -2, 8
    };

    printf("starting ... \n");

    const int L = (N * (N + 1)) >> 1;
    int arr_symm[L], arr_top[L], arr_bottom[L];
    memset(arr_symm, 0, L * sizeof(int));
    memset(arr_top, 0, L * sizeof(int));
    memset(arr_bottom, 0, L * sizeof(int));

    zip_to_array(arr_symm, matrix_symm, Symm);
    display(arr_symm, Symm);

    return 0;
}